/*
 * A Context Menu component
 * - it can be attached to any css/jquery selector,
 * - it can have it's own action-handler and scope
 * 
 * Usage: 
 * var mn = new ContextMenu({
 * 	target: '.row',
 * 	items:[
 * 		{ id: '', name:'', icon: '' },
 * 		'separator',
 * 		{ id: '', name:'', icon: '' },
 * 	],
 * 	scope: this,
 * 	onShow: function (menu){
 *		//menu.target
 *	}
 * 	handler: function (action, menu){
 *		//action, menu.target
 *	}
 * });
*/

var ContextMenu = function(conf){
	var defaults = { 
		target: $('body'), 
		scope: this, 
		onShow: function(){},
		handler: function(){}
	};
	this.conf = $.extend(defaults, conf);
	this.init();
};
ContextMenu.toString=function(){return 'XWERX Context-Menu Component';};

ContextMenu.prototype.init = function(){
	var self = this, cfg = this.conf;
	if (!cfg.items||!cfg.items.length) return;
	this.menu = $(this.getHtml(cfg.items));
	this.menu.on('click', '.menu-item', function(){										// menu item click action
		var res = cfg.handler.call(cfg.scope, this.hash.substr(1), self);
		if (res!==false) self.menu.hide();
		return false;
	});
	
	$('body')
		.on('click', cfg.target, function(){											// show menu
			self.target = $(this);
			self.show.call(self);
			cfg.onShow.call(cfg.scope, self);
			return false;
		})
		.append(this.menu.hide());
};




ContextMenu.prototype.show = function(){
	var bodyH = $('body').innerHeight(),
		btnOff = this.target.offset(),
		menuH = this.menu.outerHeight(),
		menuW = this.menu.outerWidth(),
		x = btnOff.left + (this.target.outerWidth() - menuW)/2, 
		y = btnOff.top + this.target.height() - 5;
	
	if (y + menuH > bodyH){ y = btnOff.top - menuH; this.menu.addClass('context-menu-up'); }
	else this.menu.removeClass('context-menu-up');
	
	if (x + menuW > window.innerWidth) x = window.innerWidth - menuW;	
	if (x < 0) x = 0;
	
	this.menu.css({ left: x, top: y }).show();
	
	$(document).on('mousedown.context-menu', this.documentClick);
	$(window).on('resize.context-menu', this.documentClick);
};


ContextMenu.prototype.hide = function(){
	this.menu.hide();
	$(document).off('.context-menu');
	$(window).off('.context-menu');
};



ContextMenu.prototype.getHtml = function(items){
	var content = [], i = 0, item, cls = ['context-menu'];
	for (; item = items[i++] ;){
		if (item === 'separator') content.push('<li class="separator"></li>');
		else content.push('<li><a class="menu-item" href="#',item.id,'">',(item.icon?'<span class="menu-icon '+item.icon+'"></span>':''),item.name,'</a></li>');
	}
	if (items.length == 1) cls.push('context-menu-single-item');
	if (this.conf.cls && this.conf.cls.length) cls.push(this.conf.cls);
	return '<table class="'+cls.join(' ')+'">' +
				'<tr><td class="tl"></td><td class="t"><div class="tip ttip"></div></td><td class="tr"></td></tr>' +
				'<tr><td class="l"></td><td class="content"><ul class="context-menu-list iconmenu">' + content.join('') + '</ul></td><td class="r"></td></tr>' +
				'<tr><td class="bl"></td><td class="b"><div class="tip btip"></div></td><td class="br"></td></tr>' +
			'</table>';
};



/**
 * Document click handler - expand function adds it, collapse - removes; 
 * It hides the menu when clicked elsewhere
 */
ContextMenu.prototype.documentClick = function(ev){ 
	if (!$(ev.target).closest('.context-menu-list').length){
		$('.context-menu').hide();
		$(document).off('.context-menu');
		$(window).off('.context-menu');
	}
};
